package org.apache.struts2.plugin.json.model;

/**
 * Definition of the abstract type of a JSON value. <br />
 * A JSON value is allways have a native Java type for implementation.
 * @author VERDOÏA Laurent <verdoialaurent@gmail.com>
 */
public abstract class JSONValue<T extends Object> {

    /**
     * Data containing by the JSON Type. <br />
     * If it's null, the JSON Value will be null valued.
     */
    protected T data;

    /**
     * Creation of an null valued JSON Value.
     */
    public JSONValue() {
        setNullity(true);
    }

    /**
     * Create an null object or not by the value of nullity. <br />
     * The data created will came from {@link #instanciateData()}.
     * @param nullity True for create an null valued object
     */
    public JSONValue(boolean nullity) {
        setNullity(nullity);
    }

    /**
     * Creation of an valued JSON Value.
     * @param data Data used as value
     */
    public JSONValue(T data) {
        setNullity(false);
        this.data = data;
    }

    /**
     * Indicate if the JSON Value is null valued or not
     * @return True if null valued
     */
    public boolean isNull() {
        return this.data == null;
    }

    /**
     * Definition of the nullity of the JSON Object. <br />
     * If the nullity if true, the data will be erased. Otherwise, we will 
     * create it by <code>{@link #instanciateData()}</code> call.
     * @param nullity Nullity to apply
     */
    public void setNullity(boolean nullity) {
        if (nullity == true) {
            this.data = null;
        } else if (this.data == null) {
            this.data = instanciateData();
        }
    }

    /**
     * Return a new instanciated data.
     * @return A new instanciated data
     */
    protected abstract T instanciateData();

    /**
     * Definition of the data. If data is a null pointer, the JSON Object will
     * be a null valued one.
     * @param data Data to use
     */
    public void setData(T data) {
        this.data = data;
    }

    /**
     * Return the data class storage of the value. <br />
     * Return null for a null valued Value.
     * @return Data class storage
     */
    public T getData() {
        return this.data;
    }
}
